/*
 *
 *      Copyright (c) 2018-2025, secureplat All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 * Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  Redistributions in binary form must reproduce the above copyright
 *  notice, this list of conditions and the following disclaimer in the
 *  documentation and/or other materials provided with the distribution.
 *  Neither the name of the pig4cloud.com developer nor the names of its
 *  contributors may be used to endorse or promote products derived from
 *  this software without specific prior written permission.
 *  Author: secureplat
 *
 */

package com.iwomy.secureplat.admin.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.iwomy.secureplat.admin.api.entity.SysDept;
import com.iwomy.secureplat.admin.api.entity.SysPost;
import com.iwomy.secureplat.admin.api.entity.SysUser;
import com.iwomy.secureplat.admin.api.entity.SysUserPost;
import com.iwomy.secureplat.admin.api.vo.DeptExcelVo;
import com.iwomy.secureplat.admin.api.vo.SysDeptVO;
import com.iwomy.secureplat.admin.mapper.SysDeptMapper;
import com.iwomy.secureplat.admin.mapper.SysPostMapper;
import com.iwomy.secureplat.admin.mapper.SysUserMapper;
import com.iwomy.secureplat.admin.mapper.SysUserPostMapper;
import com.iwomy.secureplat.admin.service.SysDeptService;
import com.iwomy.secureplat.common.core.util.R;
import com.iwomy.secureplat.common.data.datascope.DataScope;
import com.iwomy.secureplat.common.data.tenant.TenantContextHolder;
import com.iwomy.secureplat.common.excel.vo.ErrorMessage;
import com.iwomy.secureplat.common.security.util.SecurityUtils;
import lombok.AllArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.BindingResult;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 部门管理 服务实现类
 * </p>
 *
 * @author secureplat
 * @since 2018-01-20
 */
@Service
@AllArgsConstructor
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> implements SysDeptService {

	private final SysUserMapper userMapper;

	private final SysDeptMapper deptMapper;

	private final SysPostMapper postMapper;

	private final SysUserPostMapper userPostMapper;


	/**
	 * 删除部门
	 *
	 * @param id 部门 ID
	 * @return 成功、失败
	 */
	@Override
	@Transactional(rollbackFor = Exception.class)
	public Boolean removeDeptById(Long id) {
		// 级联删除部门
		List<Long> idList = this.listDescendant(id).stream().map(SysDept::getDeptId).collect(Collectors.toList());

		Optional.ofNullable(idList).filter(CollUtil::isNotEmpty).ifPresent(this::removeByIds);

		return Boolean.TRUE;
	}

	/**
	 * 查询全部部门树
	 *
	 * @param deptName
	 * @param parentId
	 * @return 树 部门名称
	 */
	@Override
	public List<Tree<Long>> selectTree(String deptName, Long parentId) {
		// 查询全部部门
		List<SysDept> deptAllList = deptMapper.selectList(
				Wrappers.<SysDept>lambdaQuery().like(StrUtil.isNotBlank(deptName), SysDept::getName, deptName));
		// 查询数据权限内部门
		List<Long> deptOwnIdList = deptMapper.selectListByScope(
				Wrappers.<SysDept>lambdaQuery().like(StrUtil.isNotBlank(deptName), SysDept::getName, deptName),
				DataScope.of()).stream().map(SysDept::getDeptId).collect(Collectors.toList());

		// 权限内部门
		List<TreeNode<Long>> collect = deptAllList.stream()
				.filter(dept -> dept.getDeptId().intValue() != dept.getParentId())
				.sorted(Comparator.comparingInt(SysDept::getSortOrder)).map(dept -> {
					TreeNode<Long> treeNode = new TreeNode<>();
					treeNode.setId(dept.getDeptId());
					treeNode.setParentId(dept.getParentId());
					treeNode.setName(dept.getName());
					treeNode.setWeight(dept.getSortOrder());
					// 有权限不返回标识
					Map<String, Object> extra = new HashMap<>(8);
					extra.put("isLock", !deptOwnIdList.contains(dept.getDeptId()));
					extra.put("createTime", dept.getCreateTime());
					extra.put("deviceCount", dept.getDeviceCount());
					extra.put("installedNum", dept.getInstalledNum());
					extra.put("childrenNum", dept.getChildrenNum());
					extra.put("deptType", dept.getDeptType());
					treeNode.setExtra(extra);
					return treeNode;
				})
				.filter(treeNode -> {
					Map<String, Object> extra = treeNode.getExtra();
					return extra != null && Boolean.FALSE.equals(extra.get("isLock"));
				})
				.collect(Collectors.toList());


		// 计算节点所在的深度作为层级
		Map<Long, Integer> depthMap = new HashMap<>();
		for (TreeNode<Long> node : collect) {
			int depth = calculateDepth(node, collect);
			depthMap.put(node.getId(), depth);
		}
		collect.stream().forEach(x->{
			int i = calculateDepth(x, collect);
			Map<String, Object> extra = x.getExtra();
			extra.put("level", depthMap.get(x.getId()));

		});

		// 模糊查询 不组装树结构 直接返回 表格方便编辑
		if (StrUtil.isNotBlank(deptName)) {
			return collect.stream().map(node -> {
				Tree<Long> tree = new Tree<>();
				tree.putAll(node.getExtra());
				BeanUtils.copyProperties(node, tree);
				return tree;
			}).collect(Collectors.toList());
		}

		return TreeUtil.build(collect, parentId == null ?
				this.getById(SecurityUtils.getUser().getDeptId()).getParentId() : parentId);
	}

	/**
	 * 计算部门所在层级
	 * @param node
	 * @param nodes
	 * @return
	 */
	private int calculateDepth(TreeNode<Long> node, List<TreeNode<Long>> nodes) {
		if (node.getParentId() == null) {
			return 0;
		}
		for (TreeNode<Long> parentNode : nodes) {
			if (parentNode.getId().equals(node.getParentId())) {
				return calculateDepth(parentNode, nodes) + 1;
			}
		}
		return 0;
	}

	/**
	 * 导出部门
	 *
	 * @return
	 */
	@Override
	public List<DeptExcelVo> listExcelVo() {
		List<SysDept> list = this.list();
		List<DeptExcelVo> deptExcelVos = list.stream().map(item -> {
			DeptExcelVo deptExcelVo = new DeptExcelVo();
			deptExcelVo.setName(item.getName());
			Optional<String> first = this.list().stream().filter(it -> item.getParentId().equals(it.getDeptId()))
					.map(SysDept::getName).findFirst();
			deptExcelVo.setParentName(first.orElse("根部门"));
			deptExcelVo.setSortOrder(item.getSortOrder());
			return deptExcelVo;
		}).collect(Collectors.toList());
		return deptExcelVos;
	}

	@Override
	public R importDept(List<DeptExcelVo> excelVOList, BindingResult bindingResult) {
		List<ErrorMessage> errorMessageList = (List<ErrorMessage>) bindingResult.getTarget();

		List<SysDept> deptList = this.list();
		for (DeptExcelVo item : excelVOList) {
			Set<String> errorMsg = new HashSet<>();
			boolean exsitUsername = deptList.stream().anyMatch(sysDept -> item.getName().equals(sysDept.getName()));
			if (exsitUsername) {
				errorMsg.add("部门名称已经存在");
			}
			SysDept one = this.getOne(Wrappers.<SysDept>lambdaQuery().eq(SysDept::getName, item.getParentName()));
			if (item.getParentName().equals("根部门")) {
				one = new SysDept();
				one.setDeptId(0L);
			}
			if (one == null) {
				errorMsg.add("上级部门不存在");
			}
			if (CollUtil.isEmpty(errorMsg)) {
				SysDept sysDept = new SysDept();
				sysDept.setName(item.getName());
				sysDept.setParentId(one.getDeptId());
				sysDept.setSortOrder(item.getSortOrder());
				baseMapper.insert(sysDept);
			} else {
				// 数据不合法情况
				errorMessageList.add(new ErrorMessage(item.getLineNum(), errorMsg));
			}
		}
		if (CollUtil.isNotEmpty(errorMessageList)) {
			return R.failed(errorMessageList);
		}
		return R.ok(null, "部门导入成功");
	}

	/**
	 * 查询所有子节点 （包含当前节点）
	 *
	 * @param deptId 部门ID 目标部门ID
	 * @return ID
	 */
	@Override
	public List<SysDept> listDescendant(Long deptId) {
		// 查询全部部门
		List<SysDept> allDeptList = baseMapper.selectList(Wrappers.emptyWrapper());

		// 递归查询所有子节点
		List<SysDept> resDeptList = new ArrayList<>();
		recursiveDept(allDeptList, deptId, resDeptList);

		// 添加当前节点
		resDeptList.addAll(allDeptList.stream().filter(sysDept -> deptId.equals(sysDept.getDeptId()))
				.collect(Collectors.toList()));
		return resDeptList;
	}

	/**
	 * 获取部门负责人
	 * <p>
	 * 1. 根据dept 查询用户 2. 筛选用户列表中 post
	 *
	 * @param deptId deptId
	 * @return user id list
	 */
	@Override
	public List<Long> listDeptLeader(Long deptId) {
		List<SysUser> sysUserList = userMapper
				.selectList(Wrappers.<SysUser>lambdaQuery().eq(SysUser::getDeptId, deptId));
		if (CollUtil.isEmpty(sysUserList)) {
			return null;
		}

		SysPost deptLeader = postMapper
				.selectOne(Wrappers.<SysPost>lambdaQuery().eq(SysPost::getPostCode, "DEPT_LEADER"));
		if (deptLeader == null) {
			return null;
		}

		List<Long> userIdList = sysUserList.stream().map(SysUser::getUserId).collect(Collectors.toList());
		return userPostMapper.selectList(Wrappers.<SysUserPost>lambdaQuery().in(SysUserPost::getUserId, userIdList))
				.stream().filter(post -> Objects.equals(post.getPostId(), deptLeader.getPostId()))
				.map(SysUserPost::getUserId).collect(Collectors.toList());
	}


	/**
	 * 递归查询所有子节点。
	 *
	 * @param allDeptList 所有部门列表
	 * @param parentId    父部门ID
	 * @param resDeptList 结果集合
	 */
	private void recursiveDept(List<SysDept> allDeptList, Long parentId, List<SysDept> resDeptList) {
		// 使用 Stream API 进行筛选和遍历
		allDeptList.stream().filter(sysDept -> sysDept.getParentId().equals(parentId)).forEach(sysDept -> {
			resDeptList.add(sysDept);
			recursiveDept(allDeptList, sysDept.getDeptId(), resDeptList);
		});
	}

	@Override
	public R getAuthorizeById(Long deptId) {
		Long tenantId = TenantContextHolder.getTenantId();
		TenantContextHolder.clear();
		QueryWrapper<SysDept> deptQueryWrapper = new QueryWrapper<>();
		deptQueryWrapper.eq("dept_id", deptId);
		deptQueryWrapper.eq("parent_id", 0);
		SysDept dept = deptMapper.selectOne(deptQueryWrapper);
		TenantContextHolder.setTenantId(tenantId);
		if (dept != null) {
			SysDeptVO deptVO = new SysDeptVO();
			deptVO.setDeptId(dept.getDeptId());
			deptVO.setName(dept.getName());
			deptVO.setParentId(dept.getParentId());
			return R.ok(deptVO);
		} else {
			return R.failed("该公司不在可平行过户范围内");
		}
	}


	@Override
	public List<SysDeptVO> getAllDeptList(String deptName) {
		List<SysDeptVO> deptList = new ArrayList<>();
		LambdaQueryWrapper<SysDept> wrapper= new LambdaQueryWrapper<SysDept>();
		if (StrUtil.isNotEmpty(deptName)) {
			wrapper.like(SysDept::getName, deptName);
		}
		List<SysDept> list = this.baseMapper.selectListByScope(wrapper, new DataScope());
		List<Long> deptIds = list.stream().map(SysDept::getDeptId).collect(Collectors.toList());
		wrapper.in(SysDept::getDeptId,deptIds);
		List<SysDept> sysDepts = this.deptMapper.selectList(wrapper);
		for (SysDept sysDept : sysDepts) {
			SysDeptVO deptVO = new SysDeptVO();
			deptVO.setDeptId(sysDept.getDeptId());
			deptVO.setName(sysDept.getName());
			deptVO.setSortOrder(sysDept.getSortOrder());
			deptVO.setParentId(sysDept.getParentId());
			deptVO.setTenantId(sysDept.getTenantId());
			deptList.add(deptVO);
		}
		return deptList;
	}

	@Override
	public List<Long> listByDeptId(Long deptId) {
		List<Long> objects = new ArrayList<>();
		List<Tree<Long>> trees = this.selectTree("", deptId);
		// 查询数据权限内部门
		List<Long> collect = trees.stream().map(Tree::getId).collect(Collectors.toList());
		objects.add(deptId);
		objects.addAll(collect);
		return objects.stream().distinct().collect(Collectors.toList());
	}


	@Override
	public List<Long> getDeptId(String deptName) {
		QueryWrapper<SysDept> wrapper = new QueryWrapper<>();
		wrapper.like("name", deptName);
		List<SysDept> deptList = deptMapper.selectList(wrapper);
		List<Long> deptIdList = new ArrayList<>();
		for (SysDept dept : deptList) {
			deptIdList.add(dept.getDeptId());
		}
		return deptIdList;
	}

	/**
	 * 查询单位层级
	 *
	 * @param deptId 部门ID
	 */
	@Override
	public List<SysDept> listAncestor(Long deptId) {
		// 查询全部部门
		List<SysDept> allDeptList = baseMapper.selectList(Wrappers.emptyWrapper());

		// 找到目标部门，并将其所有上级部门添加到结果列表中
		List<SysDept> resDeptList = new ArrayList<>();
		for (SysDept sysDept : allDeptList) {
			if (deptId.equals(sysDept.getDeptId())) {
				resDeptList.add(sysDept);
				Long parentId = sysDept.getParentId();
				while (parentId != null) {
					SysDept parentDept = findDeptById(allDeptList, parentId);
					if (parentDept != null) {
						resDeptList.add(parentDept);
						parentId = parentDept.getParentId();
					} else {
						parentId = null;
					}
				}
				break;
			}
		}
		// 将结果列表反转，按照从高到低的层级顺序返回
		Collections.reverse(resDeptList);

		return resDeptList;
	}

	/**
	 * 根据部门ID在部门列表中查找部门对象
	 *
	 * @param deptList 部门列表
	 * @param deptId   部门ID
	 * @return 部门对象
	 */
	private SysDept findDeptById(List<SysDept> deptList, Long deptId) {
		for (SysDept sysDept : deptList) {
			if (deptId.equals(sysDept.getDeptId())) {
				return sysDept;
			}
		}
		return null;
	}
}
